package com.william.jdbcplus.core.condition.criterion;

import java.io.Serializable;
import java.util.Collection;
import java.util.function.Function;

/**
 * Where 片段
 *
 * @author niliwei
 */
public interface Where<Wrap, R> extends Serializable {
    /**
     * 等于
     * column = ( wrap.getAll() )
     *
     * @param column 列
     * @param func   子查询
     * @return
     */
    Wrap eq(R column, Function<Wrap, Wrap> func);

    /**
     * 等于
     * column = val
     *
     * @param column 列
     * @param val    值
     * @return
     */
    Wrap eq(R column, Object val);

    /**
     * 不等于 <>
     *
     * @param column 列
     * @param func   值
     * @return
     */
    Wrap ne(R column, Function<Wrap, Wrap> func);

    /**
     * 不等于 <>
     *
     * @param column 列
     * @param val    值
     * @return
     */
    Wrap ne(R column, Object val);

    /**
     * 大于  >
     *
     * @param column 列
     * @param func   值
     * @return
     */
    Wrap gt(R column, Function<Wrap, Wrap> func);

    /**
     * 大于  >
     *
     * @param column 列
     * @param val    值
     * @return
     */
    Wrap gt(R column, Object val);

    /**
     * 大于等于  >=
     *
     * @param column
     * @param func
     * @return
     */
    Wrap ge(R column, Function<Wrap, Wrap> func);

    /**
     * 大于等于  >=
     *
     * @param column
     * @param val
     * @return
     */
    Wrap ge(R column, Object val);

    /**
     * 小于  <
     *
     * @param column
     * @param func
     * @return
     */
    Wrap lt(R column, Function<Wrap, Wrap> func);

    /**
     * 小于  <
     *
     * @param column
     * @param val
     * @return
     */
    Wrap lt(R column, Object val);

    /**
     * 小于等于  <=
     *
     * @param column
     * @param func
     * @return
     */
    Wrap le(R column, Function<Wrap, Wrap> func);

    /**
     * 小于等于  <=
     *
     * @param column
     * @param val
     * @return
     */
    Wrap le(R column, Object val);

    /**
     * BETWEEN 值1 AND 值2
     *
     * @param column
     * @param val1
     * @param val2
     * @return
     */
    Wrap between(R column, Object val1, Object val2);

    /**
     * NOT BETWEEN 值1 AND 值2
     *
     * @param column
     * @param val1
     * @param val2
     * @return
     */
    Wrap notBetween(R column, Object val1, Object val2);

    /**
     * LIKE '%值%'
     *
     * @param column
     * @param val
     * @return
     */
    Wrap like(R column, Object val);

    /**
     * NOT LIKE '%值%'
     *
     * @param column
     * @param val
     * @return
     */
    Wrap notLike(R column, Object val);

    /**
     * LIKE '%值'
     *
     * @param column
     * @param val
     * @return
     */
    Wrap likeLeft(R column, Object val);

    /**
     * LIKE '值%'
     *
     * @param column
     * @param val
     * @return
     */
    Wrap likeRight(R column, Object val);

    /**
     * IN (col1, col2...)
     *
     * @param column
     * @param collValues
     * @return
     */
    Wrap in(R column, Collection<?> collValues);

    /**
     * IN (col1, col2...)
     *
     * @param column
     * @param collValues
     * @return
     */
    Wrap notIn(R column, Collection<?> collValues);

    /**
     * 为空
     *
     * @param column
     * @return
     */
    Wrap isNull(R column);

    /**
     * 非空
     *
     * @param column
     * @return
     */
    Wrap isNotNull(R column);


    /**
     * 连接 not
     *
     * @return
     */
    Wrap not();

    /**
     * 连接 or
     *
     * @return
     */
    Wrap or();

    /**
     * 连接 and
     *
     * @return
     */
    Wrap and();

    /**
     * NOT 嵌套
     * <p>
     * 例: not(i -> i.eq("name", "李白").ne("status", "活着"))
     * </p>
     *
     * @param func 函数
     * @return wrap
     */
    Wrap not(Function<Wrap, Wrap> func);

    /**
     * OR 嵌套
     * <p>
     * 例: or(i -> i.eq("name", "李白").ne("status", "活着"))
     * </p>
     *
     * @param func 函数
     * @return wrap
     */
    Wrap or(Function<Wrap, Wrap> func);

    /**
     * AND 嵌套
     * <p>
     * 例: and(i -> i.eq("name", "李白").ne("status", "活着"))
     * </p>
     *
     * @param func 函数
     * @return wrap
     */
    Wrap and(Function<Wrap, Wrap> func);

    /**
     * 正常嵌套 不带 AND 或者 OR
     * <p>
     * 例: link(i -> i.eq("name", "李白").ne("status", "活着"))
     * </p>
     *
     * @param func 函数
     * @return Wrap
     */
    Wrap link(Function<Wrap, Wrap> func);

    /**
     * on条件
     * <p> select * from tab1, tab2 where tab1.id = tab2.id</p>
     *
     * @param r1 左列
     * @param r2 右列
     * @return
     */
    Wrap on(R r1, R r2);

    /**
     * IN (wrap.getSql())
     *
     * @param column
     * @param func
     * @return
     */
    Wrap in(R column, Function<Wrap, Wrap> func);

    /**
     * not IN (wrap.getSql())
     *
     * @param column
     * @param func
     * @return
     */
    Wrap notIn(R column, Function<Wrap, Wrap> func);

    /**
     * exists (wrap.getSql())
     *
     * @param func
     * @return
     */
    Wrap exists(Function<Wrap, Wrap> func);

    /**
     * not exists (wrap.getSql())
     *
     * @param func
     * @return
     */
    Wrap notExists(Function<Wrap, Wrap> func);

    /**
     * 拼接 sql
     * <p>!! 会有 sql 注入风险 !!</p>
     * <p>例1: connect("id = 1")</p>
     * <p>例2: connect("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")</p>
     * <p>例3: connect("date_format(dateColumn,'%Y-%m-%d') = {0}", LocalDate.now())</p>
     *
     * @param sql   脚本
     * @param value
     * @return
     */
    Wrap connect(String sql, Object... value);

}
